package com.jiehoo.java2html;



import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Map;

import com.jiehoo.utils.StringUtil;

public class ClassLink {
  HashMap<Map,String> linkMap;

  public ClassLink() {
  }

  public ClassLink(HashMap linkMap) {
    this.linkMap = linkMap;
  }

  public void put(HashMap classMap, String link) {
    if (linkMap == null) {
      linkMap = new HashMap();
    }
    linkMap.put(classMap, link);
  }

  public void putAll(ClassLink classLink) {
    if (linkMap == null) {
      linkMap = new HashMap();
    }
    linkMap.putAll(classLink.linkMap);
  }

  public String getLink(String className, String packagePath,
      String classPackage, ArrayList importedClasses) {
    if (linkMap == null || linkMap.size() == 0) {
      return null;
    }
    Iterator classMaps = linkMap.keySet().iterator();
    while (classMaps.hasNext()) {
      HashMap classMap = (HashMap) classMaps.next();
      Object path = classMap.get(className);
      if (path != null) {
        String root = (String) linkMap.get(classMap);
        String classPath = getPath(path, className, packagePath, classPackage,
            importedClasses);
        if (classPath == null) {
          return null;
        } else {
          return getRoot(root, packagePath) + classPath;
        }
      }
    }
    return null;
  }

  private String getRoot(String root, String packagePath) {
    if (root.equals("")) {
      if (packagePath != null) {
        int count = StringUtil.getSubtringCount(packagePath, "/");
        if (packagePath.length() > 0) {
          count++;
        }
        if (count > 0) {
          return Utility.fill("../", count);
        }
        return "";
      } else {
        return root;
      }
    } else if (!root.startsWith("http://") && !root.startsWith("file:///")) {
      if (packagePath != null) {
        int count = StringUtil.getSubtringCount(packagePath, "/");
        if (packagePath.length() > 0) {
          count++;
        }
        if (count > 0) {
          return Utility.fill("../", count) + root;
        }
        return root;
      } else {
        return root;
      }
    } else {
      return root;
    }
  }

  private String getPath(Object path, String className, String packagePath,
      String classPackage, ArrayList<String> importedClasses) {
    if (path instanceof String) {
      if (classPackage != null) {
        if (((String) path).startsWith(classPackage)) {
          return ((String) path);
        }
        return null;
      }
      if (importedClasses.size() > 0) {
        for (int i = 0; i < importedClasses.size(); i++) {
          String currentPackage = importedClasses.get(i);
          if (currentPackage.endsWith("/" + className)) {
            if (((String) path).startsWith(currentPackage)) {
              return ((String) path);
            }
            break;
          }
        }
        for (int i = 0; i < importedClasses.size(); i++) {
          String currentPackage = importedClasses.get(i);
          if (currentPackage.endsWith("/")) {
            String fullName = currentPackage + className;
            if (((String) path).startsWith(fullName)) {
              return ((String) path);
            }
          }
        }
      }
      if (packagePath != null) {
        if (((String) path).startsWith(packagePath)) {
          return ((String) path);
        }
      }
      if (((String) path).startsWith("java/lang/")) {
        return ((String) path);
      }
      return null;
    } else {
      ArrayList<String> pathList = (ArrayList<String>) path;
      if (classPackage != null) {
        String fullName = classPackage + className;
        for (int j = 0; j < pathList.size(); j++) {
          String currentPath =  pathList.get(j);
          if (currentPath.startsWith(fullName)) {
            return currentPath;
          }
        }
        return null;
      }
      if (importedClasses.size() > 0) {
        for (int i = 0; i < importedClasses.size(); i++) {
          String currentPackage = (String) importedClasses.get(i);
          if (currentPackage.endsWith("/" + className)) {
            for (int j = 0; j < pathList.size(); j++) {
              String currentPath = (String) pathList.get(j);
              if (currentPath.startsWith(currentPackage)) {
                return currentPath;
              }
            }
            break;
          }
        }
        for (int i = 0; i < importedClasses.size(); i++) {
          String currentPackage = (String) importedClasses.get(i);
          if (currentPackage.endsWith("/")) {
            String fullName = currentPackage + className;
            for (int j = 0; j < pathList.size(); j++) {
              String currentPath = (String) pathList.get(j);
              if (currentPath.startsWith(fullName)) {
                return currentPath;
              }
            }
          }
        }
      }
      String fullName = packagePath + "/" + className;
      for (int j = 0; j < pathList.size(); j++) {
        String currentPath = (String) pathList.get(j);
        if (currentPath.startsWith(fullName)) {
          return currentPath;
        }
      }
      fullName = "java/lang/" + className;
      for (int j = 0; j < pathList.size(); j++) {
        String currentPath = (String) pathList.get(j);
        if (currentPath.startsWith(fullName)) {
          return currentPath;
        }
      }
      return null;
    }
  }

  public static ClassLink getClassLink(String mapFilename) {
    try {
      BufferedReader buffer = new BufferedReader(new FileReader(mapFilename));
      String line = buffer.readLine();
      ClassLink classLink = new ClassLink();
      while (line != null) {
        if (line.startsWith("#") || line.length() == 0) {
          line = buffer.readLine();
          continue;
        }
        String[] array = line.split("=");
        String path;
        String link;
        URL url;
        if (array.length == 1) {
          path = line;
          int index = line.lastIndexOf("/");
          if (index >= 0) {
            link = line.substring(0, index + 1);
          } else {
            link = "";
          }
        } else {
          path = array[0];
          link = array[1];
        }
        url = getURL(path);
        HashMap map = (HashMap) com.jiehoo.utils.io.FileReader.readObject(url);
        if (map != null) {
          classLink.put(map, link);
        }
        line = buffer.readLine();
      }
      return classLink;
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  private static URL getURL(String path) {
    try {
      if (path.startsWith("http://") || path.startsWith("file:///")) {
        return new URL(path);
      } else {
        return new File(path).toURL();
      }
    }
    catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

}
